var typeLib = require('../type')
var pathLib = require('path')
var unique = require('array-unique')


module.exports = arrayUnique


/**
 * 数组去重
 * @param  {[type]} arr [description]
 * @return {[type]}     [description]
 */
function arrayUnique(arr) {
	if (!Array.isArray(arr)) {
	   throw new TypeError('array-unique expects an array.');
	}
	return [... new Set(arr) ]
}
/**
 * Array.from 转数组 (将一个可迭代结构转为数组)
 * @param  {[type]} arr [description]
 * @return {[type]}     [description]
 */
function arrayUnique2(arr) {
	return Array.from(new Set(arr))
}


/**
 * 循环+判断
 * @param  {[type]} arr [description]
 * @return {[type]}     [description]
 */
function arrayUnique3(arr) {
	var result = []
	for (var i = 0; i < arr.length; i++) {
		if( !result.includes(arr[i]) ) {
			result.push(arr[i])
		}
	}
	return result
}

/**
 * 冒泡寻找
 * @param  {[type]} arr [description]
 * @return {[type]}     [description]
 */
function arrayUnique4(arr) {
	var result = []
	for (var i = 0; i < arr.length; i++) {
		for (var j = 0; j < result.length; j++) {
			// 找到重复的元素
			if(result[j]  === arr[i])  break;
		}
		// 没有找到重复元素
		if(j === result.length) {
			result.push(arr[i])
		}
	}
	return result
}


/**
 * 不使用includes函数 两层循环
 * @param  {[type]} arr [description]
 * @return {[type]}     [description]
 */
function arrayUnique5(arr) {
	var result = arr.slice(); 
	for (var i = 0; i < arr.length; i++) {
		// 判断arr[i], 在result数组 i+1元素之后是否存在
		// 删除与arr[i] 完全相等的元素
		for (var j = i + 1; j< result.length; j++) {
			if(result[j] === arr[i]) {
				result.splice(j--, 1)
			}
		}
	}
	return result
}


/**
 * 利用对象的属性不会重复的特点 减少一层判断
 * 有缺陷, 对象的属性只能是字符串类型 
 * @param  {[type]} arr [description]
 * @return {[type]}     [description]
 */
function arrayUnique15(arr) {
	var obj = {}
	for (var i = 0; i < arr.length; i++) {
		obj[arr[i]] = i
	}
	return Object.keys(obj)
}

function test1() {

	var arr = ['a', 'b', 'c', 'c'];

	console.group()
	console.log( unique(arr) );
	console.groupEnd()

	console.log('\n-----------------------\n')

	console.group(pathLib.basename(__filename))
	console.log( arrayUnique(arr) );
	console.log( arrayUnique2(arr) );
	console.log( arrayUnique3(arr) );
	console.log( arrayUnique4(arr) );
	console.groupEnd()

	buildTest();
}

/**
 * 测试不同版本的函数，返回结果是否一致
 * @return {[type]} [description]
 */
function buildTest() {
	console.log(`\n------   buildTest ${pathLib.basename(__filename)} ... ------\n`)
	
	// console.log(isExitsFunction('arrayUnique'))
	// console.log(getTestFunList(arrayUnique))
	
	// var fnList = getTestFunList(arrayUnique)
	// var endFn  = require('./03-ArrayLast.js')(fnList)
	// console.log(endFn , typeof endFn)
	
	myTest(arrayUnique, arr);

	/**
	 * 测试不同版本的 函数返回的结果是否一致
	 * @param  {Function}  fn   [description]
	 * @param  {...[type]} args [description]
	 * @return {[type]}         [description]
	 */
	function myTest(fn, ...args) {
		var fnList = getTestFunList(fn)

		var result = []
		for (var i = 0; i < fnList.length; i++) {
			result.push(fnList[i](...args))
		}

		var trasResult = result.map(item => JSON.stringify(item))
		var uniqueTransResult = [... new Set(trasResult)]
		
		// 几组函数的结果 返回值相同
		if(uniqueTransResult.length === 1) {
			return true
		} else {
			console.group('myTest result')
			console.log(result)
			console.groupEnd()
			
			return false 
		}
	}



	/**
	 * 获取多个同一功能，不能实现的函数列表
	 * @param  {Function} fn [description]
	 * @return {[type]}      [description]
	 */
	function getTestFunList(fn) {
		if(typeof fn !== 'function') {
			throw new TypeError('the argument must be an  function ')
		}

		var fnList = [fn]
		var fnMore = null
		var x = 0 
		while(x ++ < 10 ) {
			var isBreak = false ;
			var fnArr = []
			// 不同版本的函数，命名符合一定的规则
			var fnNames = [ fn.name + x , fn.name + `V${x}`, fn.name + `v${x}` ]
			
			for (var i = 0; i < fnNames.length; i++) {
				fnMore =  isExitsFunction(fnNames[i])
				if(fnMore) {
					fnArr.push(fnMore)
					// fnMore = null
				}
			}

			// 没有找到一个函数
			if(fnArr.length === 0 && x >= 2) {
				isBreak = true
			}
			
			fnList = fnList.concat(fnArr)
			if(isBreak) break
		}
		
		return  fnList
	}


	/**
	 * 判断一个函数(字符串)是否存在
	 * @param  {[type]}  funcName        [description]
	 * @param  {Boolean} transToFunction [description]
	 * @return {Boolean}                 [description]
	 */
	function isExitsFunction(funcName, transToFunction = true) {
	  try {
	  	var transFun = eval(funcName)
	    if (typeof(transFun) == "function") {
	      return transToFunction ? transFun : true
	    }
	  } catch(e) {}
	  return false 
	}
}
